package requests

import (
	"crypto/tls"
	"errors"
	"fmt"
	"golang.org/x/net/context"
	"golang.org/x/net/proxy"
	"net"
	"net/http"
	Url "net/url"
	"strings"
	"time"
)

type requests struct {
	http.Request
	Status   string // 此次请求状态码
	Text     string // 此次请求响应包体
	HttpText string // 当前请求的报文
}

type requestInit struct {
	url     string
	TimeOut time.Duration
	Header  map[string]string
	Cookie  map[string]string
	Param   map[string]interface{}
	IsJson  bool
	IsForm  bool
	Body    []byte
	Proxy   *http.Transport
}

type Cookie map[string]string
type Header map[string]string
type Param map[string]interface{}
type Body []byte
type Proxy string

// 设置代理
func setProxy(url1 string, Rquest *requestInit) error {
	proxyUrl, err := ParseProxy(url1)
	if err != nil {
		fmt.Println(err)
		return err
	}
	// 检查代理是否可用
	err = CheckProxy(url1)
	if err != nil {
		return err
	}
	if strings.Contains(proxyUrl.Scheme, "socks") {
		Rquest.Proxy = &http.Transport{}
		dialer, _ := proxy.SOCKS5("tcp", proxyUrl.Host, nil, proxy.Direct)
		Rquest.Proxy.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
			return dialer.Dial(network, addr)
		}
	} else if proxyUrl.Scheme == "http" || proxyUrl.Scheme == "https" {
		Rquest.Proxy = &http.Transport{
			// 设置代理
			Proxy: http.ProxyURL(proxyUrl),
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		}
	}
	return nil
}

// 检查代理是否可用
func CheckProxy(url1 string) error {
	proxyUrl, err := Url.Parse(url1)
	if err != nil {
		return errors.New(fmt.Sprintf("Invalid proxy URL: %v", err))
	}
	// 检查代理是否可用
	client := &http.Client{
		Transport: &http.Transport{
			Proxy: http.ProxyURL(proxyUrl),
			DialContext: (&net.Dialer{
				Timeout:   10 * time.Second,
				KeepAlive: 10 * time.Second,
			}).DialContext,
		},
		Timeout: 10 * time.Second,
	}

	// 测试可达性
	resp, err := client.Get("http://www.baidu.com")
	if err != nil {
		return fmt.Errorf("proxy test failed: %v", err)
	}
	defer resp.Body.Close()

	// 判断返回值
	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("proxy returned non-200 status: %d", resp.StatusCode)
	}

	return nil
}

// 解析代理地址
func ParseProxy(url string) (*Url.URL, error) {
	proxyUrl, err := Url.Parse(url)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("Invalid proxy URL: %v", err))
	}
	return proxyUrl, nil
}
